package com.business.services;

import com.business.ZkClient;
import com.business.bean.ClusterInfo;
import com.business.bean.ServerInfo;
import com.business.bean.TreeNode;
import com.business.db.DerbyConn;
import com.util.HelpMe;
import com.util.TouchJdbc;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by mengdexuan on 2017/1/15 15:10.
 */
public class QueryServer {

	private TouchJdbc touchJdbc = TouchJdbc.getInstance();
	private static Connection conn = DerbyConn.getConn();
	private ZooKeeper zooKeeper = null;
	private List<String> pathList = new ArrayList<>();
	private static org.slf4j.Logger log = LoggerFactory.getLogger(QueryServer.class);

	public TreeNode getNode(String clusterId) throws Exception {

		String sql = "select ip,port from server_info where cluster_id = '" + clusterId + "' order by create_time";
		List<Map<String, Object>> mapList = touchJdbc.query4MapList(conn, sql);
		String connStr = "";
		for (Map<String, Object> map : mapList) {
			String ip = map.get("ip").toString();
			String port = map.get("port").toString();
			connStr += ip;
			connStr += ":";
			connStr += port;
			connStr += ",";
		}
		connStr = HelpMe.removeLastChar(connStr);

		zooKeeper = ZkClient.getZk(clusterId, connStr);

		TreeNode result = listChildren(clusterId, "/");
		return result;
	}

	private TreeNode listChildren(String clusterId, String path) throws Exception {
		if (!path.startsWith("/")) {
			path = "/" + path;
		}

//		log.info("zk 路径 --> "+path);

		TreeNode node = new TreeNode(clusterId, path);
		List<String> list = zooKeeper.getChildren(path, false);
		if (HelpMe.isNotNull(list)) {
			TreeNode[] arr = new TreeNode[list.size()];
			for (int i = 0; i < list.size(); i++) {
				if (!path.endsWith("/")) {
					path = path + "/";
				}
				arr[i] = listChildren(clusterId, path + list.get(i));
			}
			node.setChildren(arr);
		}
		return node;
	}


	//删除全部 ZK 节点（除了根节点）
	public void deleteAllNode(String clusterId, String path)  throws Exception {
		pathList.clear();
		nodeList(clusterId, path);

		int len = pathList.size();
		if (len>0){
			boolean flag = true;
			List<Integer> tempList = new ArrayList<>();
			ZooKeeper zooKeeper = ZkClient.getZk(clusterId);
			while (flag){//删除 ZK 节点
				for (int i=0;i<pathList.size();i++) {
					try {
						zooKeeper.delete(pathList.get(i), -1);
						log.info("删除 ZK 节点 --> "+pathList.get(i));
						tempList.add(i);
					} catch (InterruptedException e) {
//						e.printStackTrace();
					} catch (KeeperException.NotEmptyException e) {
//						e.printStackTrace();
					}catch (KeeperException.BadArgumentsException e){
						log.info("节点 --> "+pathList.get(i)+" 不允许删除！");
						tempList.add(i);
					}
				}
				if (HelpMe.isNotNull(tempList)){
					for (int temp:tempList){
						pathList.remove(temp);
					}
					tempList.clear();
				}
				if (HelpMe.isNull(pathList)){
					flag = false;
				}
			}

		}



	}


	private void nodeList(String clusterId, String path) throws Exception {
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		if (!path.equals("/")) {
			try {
				pathList.add(path);
			} catch (Exception e) {
			}
		}
		ZooKeeper zooKeeper = ZkClient.getZk(clusterId);
		List<String> list = zooKeeper.getChildren(path, false);
		if (HelpMe.isNotNull(list)) {
			for (int i = 0; i < list.size(); i++) {
				if (!path.endsWith("/")) {
					path = path + "/";
				}
				nodeList(clusterId, path + list.get(i));
			}
		}
	}


	//列出所有集群，以及集群下的所有节点
	public List<ClusterInfo> listCluster() {
		String sql = "select * from cluster_info order by create_time desc";
		List<Map<String, Object>> mapList = touchJdbc.query4MapList(conn, sql);
		mapList = HelpMe.swapMapKeyCase(mapList);
		if (HelpMe.isNotNull(mapList)) {
			List<ClusterInfo> clusterInfoList = new ArrayList<>();
			for (Map<String, Object> map : mapList) {
				String clusterId = map.get("uuid").toString();
				sql = "select * from server_info where cluster_id = '" + clusterId + "' order by create_time";
				List<Map<String, Object>> mapList2 = touchJdbc.query4MapList(conn, sql);
				if (HelpMe.isNull(mapList2)) continue;
				String clusterName = map.get("name").toString();
				mapList2 = HelpMe.swapMapKeyCase(mapList2);
				List<ServerInfo> list = new ArrayList<>();
				for (Map<String, Object> map2 : mapList2) {
					ServerInfo serverInfo = new ServerInfo();
					serverInfo.setIp(map2.get("ip").toString());
					serverInfo.setPort(Integer.parseInt(map2.get("port").toString()));
					serverInfo.setUuid(map2.get("uuid").toString());
					list.add(serverInfo);
				}
				ClusterInfo clusterInfo = new ClusterInfo(clusterId, clusterName, list);
				clusterInfoList.add(clusterInfo);
			}
			log.info("列出集群信息……");
			return clusterInfoList;
		}
		return null;
	}


	public boolean addServer(String ip, int port) {
		String uuid = HelpMe.uuid2();
		boolean flag = false;

		String values = "'" + uuid + "','" + ip + "'," + port + ",'" + HelpMe.currTime() + "'";
		String sql = "insert into server_info(uuid,ip,port,create_time) values(" + values + ")";
		try {
			touchJdbc.update(conn, sql);
			flag = true;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return flag;
	}


	public List<Map<String, Object>> clusterData() {
		String sql = "select * from cluster_info ORDER BY create_time DESC";
		List<Map<String, Object>> mapList = touchJdbc.query4MapList(conn, sql);
		if (HelpMe.isNotNull(mapList)) {
			for (Map<String, Object> map : mapList) {
				String uuid = map.get("UUID").toString();
				sql = "select count(1) from server_info where cluster_id = '" + uuid + "'";
				int count = touchJdbc.query4Int(conn, sql);
				map.put("count", count);
			}
		}
		return mapList;
	}

	public Map<String, Object> getData(int type, String uuid) {
		Map<String, Object> map = null;
		if (type == 1) {
			map = touchJdbc.query4Map(conn, "select * from cluster_info where uuid = '" + uuid + "' OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY");
		} else if (type == 2) {
			map = touchJdbc.query4Map(conn, "select * from server_info where uuid = '" + uuid + "' OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY");
		}
		Map<String, Object> result = HelpMe.swapMapKeyCase(map);
		return result;
	}


	public List<Map<String, Object>> serverData() {
		String sql = "select * from server_info ORDER BY create_time DESC";
		List<Map<String, Object>> mapList = touchJdbc.query4MapList(conn, sql);
		return mapList;
	}


	public void addData(String name, String uuid) throws Exception {
		if (HelpMe.isNotNull(uuid)) {
			String sql = "update cluster_info set name = '" + name + "' where uuid = '" + uuid + "'";
			touchJdbc.update(conn, sql);
		} else {
			String sql = "insert into cluster_info(uuid, name, create_time) VALUES ('" + HelpMe.uuid2() + "','" + name + "','" + HelpMe.currTime() + "')";
			touchJdbc.update(conn, sql);
		}
	}

	public void addData(String ip, int port, String cluster, String uuid) throws Exception {

		if (HelpMe.isNotNull(uuid)) {
			String sql = "update server_info set ip = '" + ip + "',port = " + port + ",cluster_id = '" + cluster + "' where uuid = '" + uuid + "'";
			touchJdbc.update(conn, sql);
		} else {
			String sql = "insert into server_info(uuid,ip,port,create_time,cluster_id) values('" + HelpMe.uuid2() + "','" + ip + "'," + port + ",'" + HelpMe.currTime() + "','" + cluster + "')";
			touchJdbc.update(conn, sql);
		}

	}


	public boolean delData(int flag, String uuid) throws Exception {
		String table = "";
		if (flag == 1) {
			table = "cluster_info";
			int count = touchJdbc.query4Int(conn, "select count(1) from server_info where cluster_id = '" + uuid + "'");
			if (count > 0) {
				log.info("集群下有节点，不允许删除！");
				return false;
			}
		} else if (flag == 2) {
			table = "server_info";
		}
		String sql = "delete from " + table + " where uuid = '" + uuid + "'";
		touchJdbc.update(conn, sql);
		return true;
	}


	public List<Map<String, Object>> getServerByClusterId(String clusterId) {

		String sql = "select * from server_info where cluster_id = '" + clusterId + "' order by create_time desc";

		return touchJdbc.query4MapList(conn, sql);
	}


}
